// API 请求工具
import { message } from 'antd';

// API 基础配置
const API_CONFIG = {
  // 基础URL
  baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api',
  // 默认超时时间（毫秒）
  timeout: 10000,
  // 默认请求头
  headers: {
    'Content-Type': 'application/json',
  },
};

// 请求配置接口
export interface RequestConfig extends RequestInit {
  params?: Record<string, unknown>;
  timeout?: number;
  // 请求前钩子函数
  beforeRequest?: (config: RequestConfig) => void | Promise<void>;
  // 请求后钩子函数
  afterRequest?: (response: Response, data: unknown) => void | Promise<void>;
  // 错误处理钩子函数
  onError?: (error: Error) => void;
  // 是否显示错误提示
  showErrorToast?: boolean;
  // 是否禁用默认钩子
  disableDefaultHooks?: boolean;
}

// 响应数据接口
export interface ApiResponse<T = unknown> {
  code: number;
  message: string;
  data: T;
  page?: number;
  pageSize?: number;
  total?: number;
  totalPages?: number;
}

/**
 * 处理URL查询参数
 * @param url 基础URL
 * @param params 查询参数对象
 * @returns 拼接查询参数后的完整URL
 */
const buildQueryString = (url: string, params?: Record<string, unknown>): string => {
  if (!params) return url;

  const searchParams = new URLSearchParams();
  Object.keys(params).forEach(key => {
    if (params[key] !== undefined && params[key] !== null) {
      searchParams.append(key, params[key] as string);
    }
  });

  const queryString = searchParams.toString();
  return queryString ? `${url}${url.includes('?') ? '&' : '?'}${queryString}` : url;
};

/**
 * 设置请求超时
 * @param promise fetch请求Promise
 * @param timeout 超时时间（毫秒）
 * @returns 带超时的Promise
 */
const timeoutPromise = <T>(promise: Promise<T>, timeout: number): Promise<T> => {
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      reject(new Error('请求超时'));
    }, timeout);

    promise
      .then(resolve)
      .catch(reject)
      .finally(() => clearTimeout(timer));
  });
};

/**
 * 通用请求方法
 * @param endpoint API端点
 * @param config 请求配置
 * @returns Promise<ApiResponse<T>>
 */
async function request<T = unknown>(endpoint: string, config: RequestConfig = {}): Promise<ApiResponse<T>> {
  const {
    method = 'GET',
    headers,
    params,
    body,
    timeout = API_CONFIG.timeout,
    beforeRequest,
    afterRequest,
    onError,
    showErrorToast = true,
    disableDefaultHooks = false,
    ...restConfig
  } = config;

  // 构建完整URL
  const fullUrl = buildQueryString(
    endpoint.startsWith('http') ? endpoint : `${API_CONFIG.baseURL}${endpoint}`,
    params
  );

  // 合并请求头
  const requestHeaders = {
    ...API_CONFIG.headers,
    ...headers,
  };

  // 准备请求配置
  const requestConfig: RequestInit = {
    method,
    headers: requestHeaders,
    ...restConfig,
  };

  // 如果有body且不是FormData，转换为JSON
  if (body && !(body instanceof FormData)) {
    requestConfig.body = JSON.stringify(body);
  } else if (body) {
    // 对于FormData，删除Content-Type以让浏览器自动设置
    const headers = requestConfig.headers as Record<string, string>;
    delete headers['Content-Type'];
    requestConfig.body = body;
  }

  // 执行请求前钩子 - 先执行默认的addAuthToken钩子，再执行自定义钩子
  try {
    if (!disableDefaultHooks) {
      await commonHooks.addAuthToken(requestConfig);
    }
    if (beforeRequest) {
      await beforeRequest(requestConfig);
    }
  } catch (error) {
    console.error('请求前钩子执行失败:', error);
    throw error;
  }

  try {
    // 发送请求（带超时）
    const response = await timeoutPromise(
      fetch(fullUrl, requestConfig),
      timeout
    );

    // 检查响应状态
    if (!response.ok) {
      throw new Error(`HTTP错误! 状态: ${response.status}`);
    }

    // 解析响应数据，处理空响应体
    let data: any;
    const contentType = response.headers.get('content-type');
    const contentLength = response.headers.get('content-length');
    
    // 如果响应体为空或不是JSON格式，返回默认成功响应
    if (contentLength === '0' || !contentType?.includes('application/json')) {
      data = { code: 200, message: '成功', data: null };
    } else {
      try {
        data = await response.json();
      } catch (jsonError) {
        // JSON解析失败，可能是空响应体
        data = { code: 200, message: '成功', data: null };
      }
    }

    // 执行请求后钩子 - 先执行默认的logResponseTime钩子，再执行自定义钩子
    try {
      if (!disableDefaultHooks) {
        await commonHooks.logResponseTime(response, data);
      }
      if (afterRequest) {
        await afterRequest(response, data);
      }
    } catch (error) {
      console.error('请求后钩子执行失败:', error);
      // 钩子失败不影响请求结果
    }

    // 检查业务状态码
    if (data.code && data.code !== 0 && data.code !== 200) {
      const errorMessage = data.message || '请求失败';
      if (showErrorToast) {
        message.error(errorMessage);
      }
      throw new Error(errorMessage);
    }

    return data;
  } catch (error) {
    const errorInstance = error instanceof Error ? error : new Error(String(error));
    
    // 执行错误处理钩子 - 先执行默认的handleUnauthorized钩子，再执行自定义钩子
    try {
      if (!disableDefaultHooks) {
        commonHooks.handleUnauthorized(errorInstance);
      }
      if (onError) {
        onError(errorInstance);
      } else if (showErrorToast) {
        message.error(errorInstance.message || '网络请求失败');
      }
    } catch (hookError) {
      console.error('错误处理钩子执行失败:', hookError);
    }

    throw error;
  }
}

/**
 * GET请求
 * @param endpoint API端点
 * @param config 请求配置
 * @returns Promise<ApiResponse<T>>
 */
export function get<T = unknown>(endpoint: string, config: RequestConfig = {}): Promise<ApiResponse<T>> {
  return request<T>(endpoint, {
    ...config,
    method: 'GET',
  });
}

/**
 * POST请求
 * @param endpoint API端点
 * @param data 请求数据
 * @param config 请求配置
 * @returns Promise<ApiResponse<T>>
 */
export function post<T = unknown>(
  endpoint: string,
  data?: BodyInit | Record<string, unknown>,
  config: RequestConfig = {}
): Promise<ApiResponse<T>> {
  return request<T>(endpoint, {
    ...config,
    method: 'POST',
    body: data as BodyInit,
  });
}

/**
 * PUT请求
 * @param endpoint API端点
 * @param data 请求数据
 * @param config 请求配置
 * @returns Promise<ApiResponse<T>>
 */
export function put<T = unknown>(
  endpoint: string,
  data?: BodyInit | Record<string, unknown>,
  config: RequestConfig = {}
): Promise<ApiResponse<T>> {
  return request<T>(endpoint, {
    ...config,
    method: 'PUT',
    body: data as BodyInit,
  });
}

/**
 * DELETE请求
 * @param endpoint API端点
 * @param config 请求配置
 * @returns Promise<ApiResponse<T>>
 */
export function del<T = unknown>(endpoint: string, config: RequestConfig = {}): Promise<ApiResponse<T>> {
  return request<T>(endpoint, {
    ...config,
    method: 'DELETE',
  });
}

/**
 * PATCH请求
 * @param endpoint API端点
 * @param data 请求数据
 * @param config 请求配置
 * @returns Promise<ApiResponse<T>>
 */
export function patch<T = unknown>(
  endpoint: string,
  data?: BodyInit | Record<string, unknown>,
  config: RequestConfig = {}
): Promise<ApiResponse<T>> {
  return request<T>(endpoint, {
    ...config,
    method: 'PATCH',
    body: data as BodyInit,
  });
}



// 通用请求前后钩子示例
export const commonHooks = {
  /**
   * 通用请求前钩子 - 添加认证token
   */
  addAuthToken: async (config: RequestConfig) => {
    // 从localStorage获取token，兼容旧的存储方式
    const token = localStorage.getItem('admin_token');
    if (token) {
      config.headers = {
        ...config.headers,
        Authorization: `Bearer ${token}`,
      };
    }
  },

  /**
   * 通用请求后钩子 - 记录响应时间
   */
  logResponseTime: async (response: Response, data: unknown) => {
    // 从响应头获取时间信息或使用其他方式计算
    console.log('请求完成:', {
      status: response.status,
      //url: response.url,
      data,
    });
  },

  /**
   * 通用错误处理钩子 - 处理401未授权
   */
  handleUnauthorized: (error: Error) => {
    if (error.message.includes('401') || error.message.includes('403')) {
      // 清除所有认证信息
      localStorage.removeItem('admin_token');
      localStorage.removeItem('admin_info');
      
      // 重定向到登录页
      window.location.href = '/login';
    }
  },
};


// 导出API实例
export default {
  get,
  post,
  put,
  delete: del,
  patch,
  request,
};